package com.swak.consistency.core.context;

import com.swak.annotation.ConsistencyScheme;
import com.swak.annotation.Propagation;
import com.swak.consistency.core.aspect.ConsistencyProceeding;
import com.swak.consistency.core.attribute.ConsistencyAttribute;
import com.swak.consistency.core.execption.ConsistencyException;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

/**
 * 上下文
 * 
 * @author DELL
 */
@Getter
@Setter
@Accessors(chain = true)
public abstract class ConsistencyContext implements ConsistencyAttribute {

	/**
	 * 切入点: 设置了这个属性则表示事务可以执行，如果没有这事务不能执行
	 */
	protected int depth;
	protected ConsistencyProceeding proceeding;
	protected ContextBindAttr bindAttr;
	protected Propagation propagation;
	protected ConsistencyScheme scheme;

	/**
	 * 事务是否已经开启
	 * 
	 * @return
	 */
	public abstract boolean isOpenTransaction();

	/**
	 * 执行事务
	 * 
	 * @param call
	 * @return
	 */
	public Object execute(ContextCall call) throws Throwable {
		try {
			ThreadContext.bind(this);
			return call.call();
		} finally {
			ThreadContext.remove(this);
		}
	}

	@SuppressWarnings("unchecked")
	public <T> T as() {
		return (T) this;
	}

	/**
	 * 获得唯一的事务上下文
	 * 
	 * @return
	 */
	public static <T extends ConsistencyContext> T get(ConsistencyScheme scheme) {
		ConsistencyContext context = ThreadContext.get(scheme);
		if (context == null) {
			throw new ConsistencyException("事务上下文为Null！");
		}
		return context.as();
	}

	/**
	 * 调用上下文
	 * 
	 * @author DELL
	 */
	@FunctionalInterface
	public static interface ContextCall {
		Object call() throws Throwable;
	}
}
